package org.example.logic

import java.util

import com.alibaba.fastjson.serializer.SerializerFeature
import com.alibaba.fastjson.{JSON, JSONObject}
import org.example.common.Logging
import org.example.dao.{AlarmEvidence, DrivingContinued, DrivingContinuedIndex, DrivingPeriod, DrivingPeriodIndex, VehicleAlarmEvidence}
import org.example.utils.{CommonUtils, EsUtils}
import io.searchbox.core.{Search, SearchResult}
import org.apache.commons.collections.{CollectionUtils, MapUtils}
import org.apache.commons.lang3.StringUtils
import org.apache.commons.lang3.time.FastDateFormat
import org.elasticsearch.index.query.QueryBuilders
import org.elasticsearch.search.builder.SearchSourceBuilder
import org.joda.time.format.{DateTimeFormat, DateTimeFormatter}
import org.joda.time.{DateTime, Seconds}
import redis.clients.jedis.Jedis

import scala.collection.mutable.ListBuffer

/**
 * @Description 行驶周期相关
 * @Date  2021/7/13
 **/
object PeriodProcess extends Logging{
  /**
    * 存当前周期的报警id和时间及驾驶时长
    * @param key
    * @param warnTypeCode
    * @param evidence
    * @param jedis
    */
  def updatePeriodWarnTimes(key: String, warnTypeCode: String, evidence: AlarmEvidence, jedis: Jedis): Unit = {
    val evidences = jedis.hget(key, warnTypeCode)
    var evidenceList: util.List[AlarmEvidence] = new util.ArrayList[AlarmEvidence]()
    if (StringUtils.isNotEmpty(evidences)) {
      evidenceList = JSON.parseArray(evidences, classOf[AlarmEvidence])
      evidenceList.add(evidence)
    } else {
      evidenceList.add(evidence)
    }
    val value = JSON.toJSONString(evidenceList, SerializerFeature.QuoteFieldNames)
    // 存报数据
    jedis.hset(key, warnTypeCode, value)
  }

  /**
    * 存当前周期的报警id和时间及驾驶时长,且设置过期时间为当天
    * @param key
    * @param warnTypeCode
    * @param evidence
    * @param jedis
    */
  def updatePeriodWarnTimes(key: String, warnTypeCode: String, evidence: AlarmEvidence, jedis: Jedis, isExpire: Boolean): Unit = {
    updatePeriodWarnTimes(key, warnTypeCode, evidence, jedis)
    if(isExpire){
      jedis.expire(key, CommonUtils.getSecondsNextDay())
    }
  }

  /**
    * 存当前周期的报警id和时间及驾驶时长,且设置过期时间为当天
    * @param key
    * @param alarms
    * @param jedis
    */
  def updatePeriodWarnTimes(key: String, alarms: ListBuffer[VehicleAlarmEvidence], jedis: Jedis, isExpire: Boolean): Unit = {
    updatePeriodWarnTimes(key, alarms, jedis)
    if(isExpire){
      jedis.expire(key, CommonUtils.getSecondsNextDay())
    }
  }

  /**
    * 存当前周期的报警id和时间及驾驶时长
    * @param key
    * @param alarms
    * @param jedis
    */
  def updatePeriodWarnTimes(key: String, alarms: ListBuffer[VehicleAlarmEvidence], jedis: Jedis): Unit = {
    if(alarms.nonEmpty){
      val map = new util.HashMap[String, String]()
      val fields = alarms.map(x => x.field).toArray
      val oldEvidenceList = jedis.hmget(key, fields: _*)

      for(i <- 0 until alarms.size){
        val vehicleAlarmEvidence: VehicleAlarmEvidence = alarms(i)
        val evidences = oldEvidenceList.get(i)
        var evidenceList: util.List[AlarmEvidence] = vehicleAlarmEvidence.alarmEvidence
        if(StringUtils.isNotEmpty(evidences)){
          evidenceList = JSON.parseArray(evidences, classOf[AlarmEvidence])
          evidenceList.addAll(vehicleAlarmEvidence.alarmEvidence)
        }
        val value = JSON.toJSONString(evidenceList, SerializerFeature.QuoteFieldNames)
        map.put(vehicleAlarmEvidence.field, value)
      }
      // 存报数据
      jedis.hmset(key, map)
    }
  }

  /**
    * 更新车辆行驶周期
    * @param vehicleNo
    * @param vehicleColor
    * @param licenseNumber
    * @param driverName
    * @param cardLicenseNumber
    * @param cardDriverName
    * @param drivingDuration
    * @param drivingMileage
    * @param tripStartTime
    * @param tripEndTime
    * @param jedis
    */
  def updateDrivingPeriod(vehicleNo: String, vehicleColor: String, licenseNumber: String, driverName: String,
                          cardLicenseNumber: String, cardDriverName: String, drivingDuration: Int, drivingMileage: Double,
                          tripStartTime: String, tripEndTime: String,
                          jedis: Jedis): Unit = {
    val millis = DateTime.parse(tripStartTime, DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).getMillis
    val id = vehicleNo + "_" + vehicleColor + "_" + driverName + "_" + millis
    val drivingPeriodIndex = DrivingPeriodIndex(id, vehicleNo, vehicleColor, licenseNumber, driverName, cardLicenseNumber,
      cardDriverName, drivingDuration, drivingMileage, tripStartTime, tripEndTime)
    val jestClient = EsUtils.getClient()
    EsUtils.insertIntosEs(jestClient, "driving_period_index", drivingPeriodIndex, id, "driving_period_type")
    jestClient.close()
    jedis.del("riskTimes:" + vehicleNo + "#" + vehicleColor + "_" + millis)
  }

  /**
    * 获取在上一个有效周期之内的驾驶员
    * @param driverName
    * @param licenseNumber
    * @param businessTime
    * @param lastDateTime
    * @param forPattern
    * @return
    */
  def getCurrDriver(driverName:String, licenseNumber:String, businessTime: String, lastDateTime: String, forPattern: DateTimeFormatter): (String, String) ={
    var currDriverName = ""
    var currLicenseNumber = ""
    if (StringUtils.isNotEmpty(businessTime) && StringUtils.isNotEmpty(lastDateTime)) {
      try {
        val businessMillis = DateTime.parse(businessTime, forPattern).getMillis
        val lastMillis = DateTime.parse(lastDateTime, forPattern).getMillis
        if(lastMillis <= businessMillis){
          currDriverName = driverName
          currLicenseNumber = licenseNumber
        }
      } catch {
        case e: Exception => {
          error(s"业务日期格式不对:${businessTime},${lastDateTime}")
        }
      }
    }
    (currDriverName, currLicenseNumber)
  }

  /**
    * 获取人脸识别和ic卡较新的一条驾驶员信息
    * @param driverName
    * @param licenseNumber
    * @param businessTime
    * @param signDriverName
    * @param signLicense
    * @param signInTime
    * @param forPattern
    * @return
    */
  def getNewDriver(driverName: String, licenseNumber: String, businessTime: String, signDriverName: String, signLicense: String, signInTime: String, forPattern: DateTimeFormatter): (String, String) ={
    //当前车辆的驾驶人
    var currDriverName = driverName
    //当前车辆的驾驶员从业证号
    var currLicense = licenseNumber
    //如果有登签数据后来，当成行驶周期结束
    if (StringUtils.isNotEmpty(businessTime) && StringUtils.isNotEmpty(signInTime)) {
      try {
        val businessMillis = DateTime.parse(businessTime, forPattern).getMillis
        val signInMillis = DateTime.parse(signInTime, forPattern).getMillis
        if (signInMillis > businessMillis) {
          currDriverName = signDriverName
          currLicense = signLicense
        }
      } catch {
        case e: Exception => {
          error(s"业务日期格式不对:${businessTime},${signInTime}")
        }
      }
    } else if (StringUtils.isEmpty(driverName)) {
      currDriverName = signDriverName
      currLicense = signLicense
    }
    (currDriverName, currLicense)
  }


  /**
    *
    * 行驶周期的界定
    *
    * @param messageInfo
    * @param jedis
    */
  def drivingPeriod(messageInfo: JSONObject, jedis: Jedis): (Boolean, String, Int, Double) = {
    var periodStatus = (false, "", 0, 0.0D)
    val forPattern = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")
    val vehicleNo: String = messageInfo.getString("vehicleNo")
    val vehicleColor: String = messageInfo.getString("vehicleColor")
    val primaryKey = vehicleNo + "#" + vehicleColor
    val dateTime: String = messageInfo.getString("dateTime")
    val speed: String = messageInfo.getString("vec1")
    val latitude = BigDecimal.decimal(java.lang.Double.parseDouble(messageInfo.getString("lat")) * 0.000001).setScale(6, BigDecimal.RoundingMode.HALF_UP).toDouble
    val longitude = BigDecimal.decimal(java.lang.Double.parseDouble(messageInfo.getString("lon")) * 0.000001).setScale(6, BigDecimal.RoundingMode.HALF_UP).toDouble

    if (StringUtils.isNotEmpty(dateTime)) {
      //当前车辆驾驶信息
      val driverInfo: util.Map[String, String] = jedis.hgetAll("driverInfo:" + primaryKey)
      //当前车辆驾驶人
      var driverName = ""
      //人脸识别业务时间
      var businessTime = ""
      var licenseNumber = ""
      if (MapUtils.isNotEmpty(driverInfo) && driverInfo.containsKey("driverName")) {
        driverName = driverInfo.get("driverName")
        businessTime = driverInfo.get("businessTime")
        licenseNumber = driverInfo.get("licenseNumber")
      }
      //驾驶员登签数据
      val driverSign = jedis.hgetAll("driverSign:" + primaryKey)
      //驾驶员
      var signDriverName = ""
      //驾驶员上班时间
      var signInTime = ""
      //驾驶员从业证号
      var signLicense = ""
      if (MapUtils.isNotEmpty(driverSign) && "1".equals(driverSign.get("state"))) {
        signDriverName = driverSign.get("driverName")
        signInTime = driverSign.get("time")
        signLicense = driverSign.get("licence")
      }

      //如果有登签数据后来，当成行驶周期结束
      val newDriverInfo = getNewDriver(driverName, licenseNumber, businessTime, signDriverName, signLicense, signInTime, forPattern)
      //当前车辆的驾驶人
      var currDriverName = newDriverInfo._1
      //当前车辆的驾驶员从业证号
      var currLicense = newDriverInfo._2

      //行驶周期
      val drivingPeriodStr: String = jedis.hget("drivingPeriod", primaryKey)
      //休息时长
      val restTime: String = jedis.hget("restTime", primaryKey)
      if (StringUtils.isNotEmpty(drivingPeriodStr)) {
        //行驶周期
        val drivingPeriod = JSON.parseObject(drivingPeriodStr, classOf[DrivingPeriod])
        //上次累计时长
        val lastTotalTime: Int = drivingPeriod.lt
        //行程开始时间
        val tripStartTime: String = drivingPeriod.ts
        //上次定位时间
        val lastLocationTime: String = drivingPeriod.llt
        //上次定位经度
        val lastLatitude = drivingPeriod.lat
        //上次定位纬度
        val lastLongitude = drivingPeriod.lng
        //上次驾驶人
        val oldDriverName = drivingPeriod.ldn
        //上次驾驶人从业资格证号
        val oldLicense = drivingPeriod.lln
        //上次行驶里程数
        val distance = drivingPeriod.cm
        //行驶瞬时速度
        var newSpeed = speed.toDouble
        //获取周期内的最新人脸识别信息
        val currFaceDriver = getCurrDriver(driverName, licenseNumber, businessTime, tripStartTime, forPattern)
        driverName = currFaceDriver._1
        licenseNumber = currFaceDriver._2
        //如果有登签数据后来，当成行驶周期结束
        val currNewDriverInfo = getNewDriver(driverName, licenseNumber, businessTime, signDriverName, signLicense, signInTime, forPattern)
        //当前车辆的驾驶人
        currDriverName = currNewDriverInfo._1
        //当前车辆的驾驶员从业证号
        currLicense = currNewDriverInfo._2

        val lastLocationDate = DateTime.parse(lastLocationTime, forPattern)
        val locationDate = DateTime.parse(dateTime, forPattern)
        val seconds = Seconds.secondsBetween(lastLocationDate, locationDate).getSeconds
        var intervalSecond = seconds
        var newLocationTime = dateTime
        var newLatitude = latitude
        var newLongitude = longitude
        //如果接收到迟到数据，记此次间隔时间为0，当前存入Redis时间为上次记录的时间
        if (seconds < 0) {
          newLocationTime = lastLocationTime
          newLatitude = lastLatitude
          newLongitude = lastLongitude
          intervalSecond = 0
          newSpeed = drivingPeriod.sd
        }
        //断电超过20分钟,新增速度为0判断条件
        if (seconds >= 1200 || (StringUtils.isNotEmpty(currDriverName) && StringUtils.isNotEmpty(oldDriverName) && !currDriverName.equals(oldDriverName))) {
          //断电20分钟或者换驾驶员的情况周期结束，开启新的周期
          val period = DrivingPeriod(0, currLicense, currDriverName, licenseNumber, driverName, signLicense,
            signDriverName, newLocationTime, newLocationTime, newLatitude, newLongitude, 0.0D, newSpeed)
          jedis.hset("drivingPeriod", primaryKey, JSON.toJSONString(period, SerializerFeature.QuoteFieldNames))
          //周期重新累计时，删除挪车点
          jedis.hdel("movePoint", primaryKey)
          if(lastTotalTime > 0){
            updateDrivingPeriod(vehicleNo, vehicleColor, drivingPeriod.ln, drivingPeriod.dn, drivingPeriod.cln,
              drivingPeriod.cdn, lastTotalTime, distance, tripStartTime, lastLocationTime, jedis)
            periodStatus = (true, tripStartTime, lastTotalTime, distance)
          }
        } else if (speed.toDouble > 0) { //断电不超过20分钟
          //时间累计
          val cumulativeTime = intervalSecond + lastTotalTime
          //行驶里程累计
          val cumulativeDistance = CommonUtils.getDistance(newLatitude, newLongitude, lastLatitude, lastLongitude) + distance
          //更新当前驾驶人
          if (StringUtils.isNotEmpty(currDriverName)) {
            drivingPeriod.setLln(currLicense)
            drivingPeriod.setLdn(currDriverName)
          }
          //更新人脸识别驾驶人
          if(StringUtils.isNotEmpty(driverName)){
            drivingPeriod.setLn(licenseNumber)
            drivingPeriod.setDn(driverName)
          }
          //更新登签数据
          if(StringUtils.isNotEmpty(signDriverName)){
            drivingPeriod.setCln(signLicense)
            drivingPeriod.setCdn(signDriverName)
          }
          //更新周期开始时间
          if(lastTotalTime == 0 && drivingPeriod.sd == 0.0){
            drivingPeriod.setTs(newLocationTime)
            drivingPeriod.setLt(lastTotalTime)
          }else{
            drivingPeriod.setLt(cumulativeTime)
          }

          drivingPeriod.setSd(speed.toDouble)
          drivingPeriod.setLlt(newLocationTime)
          drivingPeriod.setLat(newLatitude)
          drivingPeriod.setLng(newLongitude)
          drivingPeriod.setCm(cumulativeDistance)
          //数据存入redis
          jedis.hset("drivingPeriod", primaryKey, JSON.toJSONString(drivingPeriod, SerializerFeature.QuoteFieldNames))

          var num = 0
          if (StringUtils.isNotEmpty(restTime)) {
            //如果速度小于20，则记录一次
            if (speed.toDouble <= 20.0) {
              val zeroTimes: Array[String] = restTime.split("\\|")
              val movePoint = jedis.hget("movePoint", primaryKey)
              if (StringUtils.isNotEmpty(movePoint)) {
                val movePoints: Array[String] = movePoint.split(",")
                if (movePoints.size < 5) {
                  jedis.hset("movePoint", primaryKey, movePoints.mkString(",") + "," + newLocationTime)
                } else {
                  val endSeat = movePoints.drop(1)
                  jedis.hset("movePoint", primaryKey, endSeat.mkString(",") + "," + newLocationTime)
                }
              } else {
                jedis.hset("movePoint", primaryKey, newLocationTime)
              }
              num = zeroTimes(2).toInt
              jedis.hset("restTime", primaryKey, zeroTimes(0) + "|" + zeroTimes(1) + "|" + (num + 1))
            } else {
              //速度大于20的情况
              jedis.hdel("movePoint", primaryKey)
              //map重新置为空
              jedis.hset("restTime", primaryKey, 0 + "|" + newLocationTime + "|" + 0)
            }
          }
        } else {
          //速度为0的情况
          if (StringUtils.isNotEmpty(restTime)) {
            val restTimeArr: Array[String] = restTime.split("\\|")
            val restInterval: Int = restTimeArr(0).toInt
            val lastRestTime: String = restTimeArr(1)
            val num: Int = restTimeArr(2).toInt
            val lastRestDate = DateTime.parse(lastRestTime, forPattern)
            val speedSeconds = Seconds.secondsBetween(lastRestDate, locationDate).getSeconds
            var restIntervalSecond = restInterval
            var curSpeedTime = lastRestTime
            if (speedSeconds > 0) {
              restIntervalSecond = restInterval + speedSeconds
              curSpeedTime = dateTime
            }
            val movePoint: String = jedis.hget("movePoint", primaryKey)
            if (StringUtils.isNotEmpty(movePoint)) {
              val movePoints = movePoint.split(",")
              val firstPoint = DateTime.parse(movePoints(0), forPattern)
              val seconds1: Int = Seconds.secondsBetween(firstPoint, locationDate).getSeconds
              //休息20分钟，中间有挪车的情况周期结束，开启新的周期
              if (seconds1 >= 1200) {
                val period = DrivingPeriod(0, oldLicense, oldDriverName, drivingPeriod.ln, drivingPeriod.dn, drivingPeriod.cln,
                  drivingPeriod.cdn, newLocationTime, newLocationTime, newLatitude, newLongitude, 0.0D, speed.toDouble)
                if(StringUtils.isNotEmpty(currDriverName)){
                  period.setLln(currLicense)
                  period.setLdn(currDriverName)
                }
                //更新人脸识别驾驶人
                drivingPeriod.setLn(licenseNumber)
                drivingPeriod.setDn(driverName)
                //更新登签数据
                if(StringUtils.isNotEmpty(signDriverName)){
                  drivingPeriod.setCln(signLicense)
                  drivingPeriod.setCdn(signDriverName)
                }
                jedis.hset("drivingPeriod", primaryKey, JSON.toJSONString(period, SerializerFeature.QuoteFieldNames))
                //周期重新累计时，删除挪车点
                jedis.hdel("movePoint", primaryKey)
                if(lastTotalTime > 0) {
                  updateDrivingPeriod(vehicleNo, vehicleColor, licenseNumber, driverName, signLicense,
                    signDriverName, lastTotalTime, distance, tripStartTime, lastLocationTime, jedis)
                  periodStatus = (true, tripStartTime, lastTotalTime, distance)
                }
              } else {
                //继续累计时长
                jedis.hset("restTime", primaryKey, restIntervalSecond + "|" + curSpeedTime + "|" + num)
              }
            } else {
              //休息20分钟中间有速度小于二十，并且不超过五次的情况当成挪车，重置周期
              if (restIntervalSecond >= 1200 && num <= 5) {
                val period = DrivingPeriod(0, oldLicense, oldDriverName, licenseNumber, driverName, signLicense,
                  signDriverName, newLocationTime, newLocationTime, newLatitude, newLongitude, 0.0D, speed.toDouble)
                if(StringUtils.isNotEmpty(currDriverName)){
                  period.setLln(currLicense)
                  period.setLdn(currDriverName)
                }
                //更新人脸识别驾驶人
                drivingPeriod.setLn(licenseNumber)
                drivingPeriod.setDn(driverName)

                //更新登签数据
                if(StringUtils.isNotEmpty(signDriverName)){
                  drivingPeriod.setCln(signLicense)
                  drivingPeriod.setCdn(signDriverName)
                }
                jedis.hset("drivingPeriod", primaryKey, JSON.toJSONString(period, SerializerFeature.QuoteFieldNames))
                //周期重新累计时，删除挪车点
                jedis.hdel("movePoint", primaryKey)
                if(lastTotalTime > 0){
                  updateDrivingPeriod(vehicleNo, vehicleColor, drivingPeriod.ln, drivingPeriod.dn, drivingPeriod.cln,
                    drivingPeriod.cdn, lastTotalTime, distance, tripStartTime, lastLocationTime, jedis)
                  periodStatus = (true, tripStartTime, lastTotalTime, distance)
                }
              } else {
                //新增速度为0判断
                jedis.hset("restTime", primaryKey, restIntervalSecond + "|" + curSpeedTime + "|" + num)
              }
            }
          } else {
            jedis.hset("restTime", primaryKey, "0|" + newLocationTime + "|0")
          }
        }
      } else {
        val period = DrivingPeriod(0, currLicense, currDriverName, licenseNumber, driverName, signLicense,
          signDriverName, dateTime, dateTime, latitude, longitude, 0.0D, speed.toDouble)
        jedis.hset("drivingPeriod", primaryKey, JSON.toJSONString(period, SerializerFeature.QuoteFieldNames))
        periodStatus = (true, dateTime, 0, 0.0D)
      }
    }
    periodStatus
  }

  /**
    *
    * 连续驾驶详情
    *
    * @param messageInfo
    * @param jedis
    */
  def drivingContinued(messageInfo: JSONObject, jedis: Jedis): Unit = {
    val forPattern = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")
    val vehicleNo: String = messageInfo.getString("vehicleNo")
    val vehicleColor: String = messageInfo.getString("vehicleColor")
    val primaryKey = vehicleNo + "#" + vehicleColor
    val dateTime: String = messageInfo.getString("dateTime")
    val speed: String = messageInfo.getString("vec1")

    if (StringUtils.isNotEmpty(dateTime)) {
      //当前车辆驾驶信息
      val driverInfo: util.Map[String, String] = jedis.hgetAll("driverInfo:" + primaryKey)
      //当前车辆驾驶人
      var driverName = ""
      //人脸识别业务时间
      var businessTime = ""
      //人脸识别驾驶证号
      var licenseNumber = ""
      if (MapUtils.isNotEmpty(driverInfo) && driverInfo.containsKey("driverName")) {
        driverName = driverInfo.get("driverName")
        businessTime = driverInfo.get("businessTime")
        licenseNumber = driverInfo.get("licenseNumber")
      }
      //驾驶员登签数据
      val driverSign = jedis.hgetAll("driverSign:" + primaryKey)
      //驾驶员
      var signDriverName = ""
      //驾驶员上班时间
      var signInTime = ""
      //驾驶员从业证号
      var signLicense = ""
      if (MapUtils.isNotEmpty(driverSign) && "1".equals(driverSign.get("state"))) {
        signDriverName = driverSign.get("driverName")
        signInTime = driverSign.get("time")
        signLicense = driverSign.get("licence")
      }

      //行驶周期
      val drivingContinuedStr: String = jedis.hget("drivingContinued", primaryKey)
      //休息时长
      val restContinuedTime: String = jedis.hget("restContinuedTime", primaryKey)
      if (StringUtils.isNotEmpty(drivingContinuedStr)) {
        //行驶周期
        val drivingContinued = JSON.parseObject(drivingContinuedStr, classOf[DrivingContinued])
        //上次人脸识别累计时长
        val lastTotalTime: Int = drivingContinued.lt
        //上次ic卡累计时长
        val lastCardTotalTime: Int = drivingContinued.lct
        //人脸识别行程开始时间
        val tripStartTime: String = drivingContinued.ts
        val tripStartMillis = DateTime.parse(tripStartTime, forPattern).getMillis
        //IC卡行程开始时间
        val cardTripStartTime: String = drivingContinued.cts
        val cardTripStartMillis = DateTime.parse(cardTripStartTime, forPattern).getMillis
        //上次定位时间
        val lastLocationTime: String = drivingContinued.llt
        //上次驾驶人
        val oldDriverName = drivingContinued.dn
        //上次驾驶人从业资格证号
        val oldLicense = drivingContinued.ln
        //上次IC卡驾驶人
        val oldCardDriverName = drivingContinued.cdn
        //上次IC卡驾驶人从业资格证号
        val oldCardLicense = drivingContinued.cln
        //行驶瞬时速度
        var newSpeed = speed.toDouble

        val lastLocationDate = DateTime.parse(lastLocationTime, forPattern)
        val locationDate = DateTime.parse(dateTime, forPattern)
        val seconds = Seconds.secondsBetween(lastLocationDate, locationDate).getSeconds
        var intervalSecond = seconds
        var newLocationTime = dateTime
        //如果接收到迟到数据，记此次间隔时间为0，当前存入Redis时间为上次记录的时间
        if (seconds < 0) {
          newLocationTime = lastLocationTime
          intervalSecond = 0
          newSpeed = drivingContinued.sd
        }
        //断电超过20分钟,新增速度为0判断条件
        if (seconds >= 1200) {
          //断电20分钟的情况周期结束，开启新的周期
          //新的人脸识别
          var currDriverName = ""
          var currLicenseNumber = ""
          if (StringUtils.isNotEmpty(businessTime)) {
            try {
              val businessMillis = DateTime.parse(businessTime, forPattern).getMillis
              if(businessMillis > lastLocationDate.getMillis){
                currDriverName = driverName
                currLicenseNumber = licenseNumber
              }
            } catch {
              case e: Exception => {
                error(s"业务日期格式不对:${businessTime}")
              }
            }
          }
          //新的IC卡信息
          var currCardDriverName = oldCardDriverName
          var currCardLicenseNumber = oldCardLicense
          if (StringUtils.isNotEmpty(signDriverName)) {
            currCardDriverName = signDriverName
            currCardLicenseNumber = signLicense
          }

          val period = DrivingContinued(0, currLicenseNumber, currDriverName, 0, currCardLicenseNumber,
            currCardDriverName, newLocationTime, newLocationTime, newLocationTime, newSpeed)
          jedis.hset("drivingContinued", primaryKey, JSON.toJSONString(period, SerializerFeature.QuoteFieldNames))
          //周期重新累计时，删除挪车点
          jedis.hdel("movePointContinued", primaryKey)

          val endTime = lastLocationDate.getMillis.toString
          if(lastTotalTime > 0) {
            //更新人脸识别的行程信息
            val drivingContinuedIndex = DrivingContinuedIndex(vehicleNo, vehicleColor, oldLicense, oldDriverName, tripStartMillis.toString, endTime, "1")
            CommonUtils.updateDrivingContinued(drivingContinuedIndex)
          }
          if(lastCardTotalTime > 0) {
            //更新ic卡的行程信息
            val signDrivingContinuedIndex = DrivingContinuedIndex(vehicleNo, vehicleColor, oldCardLicense, oldCardDriverName, cardTripStartMillis.toString, endTime, "2")
            CommonUtils.updateDrivingContinued(signDrivingContinuedIndex)
          }
        } else if(StringUtils.isNotEmpty(oldDriverName) && StringUtils.isNotEmpty(driverName) && !oldDriverName.equals(driverName)) {
          //定位速度
          drivingContinued.setSd(speed.toDouble)
          //定位时间
          drivingContinued.setLlt(newLocationTime)
          //人脸识别行程开始时间
          drivingContinued.setTs(newLocationTime)
          //人脸识别驾驶人从业证号
          drivingContinued.setLn(licenseNumber)
          //人脸识别驾驶人姓名
          drivingContinued.setDn(driverName)
          //人脸识别累计时长
          drivingContinued.setLt(0)

          //更新新的打卡数据
          if (StringUtils.isNotEmpty(signDriverName)) {
            //更新打卡人
            if(StringUtils.isEmpty(oldCardDriverName)){
              val drivingContinuedIndex = DrivingContinuedIndex(vehicleNo, vehicleColor, signLicense, signDriverName, cardTripStartMillis.toString, null, "2")
              CommonUtils.updateDrivingContinued(drivingContinuedIndex)
            }
            //ic卡驾驶人从业证号
            drivingContinued.setCln(signLicense)
            //ic卡驾驶人姓名
            drivingContinued.setCdn(signDriverName)
          }

          jedis.hset("drivingContinued", primaryKey, JSON.toJSONString(drivingContinued, SerializerFeature.QuoteFieldNames))
          //周期重新累计时，删除挪车点
          jedis.hdel("movePointContinued", primaryKey)
          if(lastTotalTime > 0){
            //更新人脸识别的行程信息
            val drivingContinuedIndex = DrivingContinuedIndex(vehicleNo, vehicleColor, oldLicense, oldDriverName, tripStartMillis.toString, lastLocationDate.getMillis.toString, "1")
            CommonUtils.updateDrivingContinued(drivingContinuedIndex)
          }
        } else if (StringUtils.isNotEmpty(oldCardDriverName) && StringUtils.isNotEmpty(signDriverName) && !oldCardDriverName.equals(signDriverName)) {
          //定位速度
          drivingContinued.setSd(speed.toDouble)
          //定位时间
          drivingContinued.setLlt(newLocationTime)
          //ic卡行程开始时间
          drivingContinued.setCts(newLocationTime)
          //ic卡驾驶人从业证号
          drivingContinued.setCln(signLicense)
          //ic卡驾驶人姓名
          drivingContinued.setCdn(signDriverName)
          //ic卡累计时长
          drivingContinued.setLct(0)
          //更新人脸识别驾驶人
          if (StringUtils.isNotEmpty(businessTime)) {
            try {
              val businessMillis = DateTime.parse(businessTime, forPattern).getMillis
              if(businessMillis > tripStartMillis){
                //更新人脸识别驾驶人
                if(StringUtils.isEmpty(oldDriverName)){
                  val drivingContinuedIndex = DrivingContinuedIndex(vehicleNo, vehicleColor, licenseNumber, driverName, tripStartMillis.toString, null, "1")
                  CommonUtils.updateDrivingContinued(drivingContinuedIndex)
                }
                drivingContinued.setLn(licenseNumber)
                drivingContinued.setDn(driverName)
              }
            } catch {
              case e: Exception => {
                error(s"业务日期格式不对:${businessTime}")
              }
            }
          }

          jedis.hset("drivingContinued", primaryKey, JSON.toJSONString(drivingContinued, SerializerFeature.QuoteFieldNames))
          //周期重新累计时，删除挪车点
          jedis.hdel("movePointContinued", primaryKey)
          if(lastCardTotalTime > 0){
            //更新IC卡的行程信息
            val drivingContinuedIndex = DrivingContinuedIndex(vehicleNo, vehicleColor, oldCardLicense, oldCardDriverName, cardTripStartMillis.toString, lastLocationDate.getMillis.toString, "2")
            CommonUtils.updateDrivingContinued(drivingContinuedIndex)
          }
        } else if (speed.toDouble > 0) { //断电不超过20分钟
          //人脸识别的周期开始
          var faceDrivingContinued: Option[DrivingContinuedIndex] = None
          //IC卡的周期开始
          var cardDrivingContinued: Option[DrivingContinuedIndex] = None
          //时间累计
          val cumulativeTime = intervalSecond + lastTotalTime
          //ic卡时间累计
          val cardCumulativeTime = intervalSecond + lastCardTotalTime

          //新的人脸识别
          if (StringUtils.isNotEmpty(businessTime)) {
            try {
              val businessMillis = DateTime.parse(businessTime, forPattern).getMillis
              if(businessMillis > tripStartMillis){
                //更新人脸识别的行程信息
                if(StringUtils.isEmpty(oldDriverName)){
                  faceDrivingContinued = Some(DrivingContinuedIndex(vehicleNo, vehicleColor, licenseNumber, driverName, tripStartMillis.toString, null, "1"))
                }
                drivingContinued.setLn(licenseNumber)
                drivingContinued.setDn(driverName)
              }
            } catch {
              case e: Exception => {
                error(s"业务日期格式不对:${businessTime}")
              }
            }
          }

          //更新新的打卡数据
          if (StringUtils.isNotEmpty(signDriverName)) {
            if(StringUtils.isEmpty(oldCardDriverName)){
              cardDrivingContinued = Some(DrivingContinuedIndex(vehicleNo, vehicleColor, signLicense, signDriverName, cardTripStartMillis.toString, null, "2"))
            }
            drivingContinued.setCln(signLicense)
            drivingContinued.setCdn(signDriverName)
          }

          //更新周期开始时间
          if(lastTotalTime == 0){
            //速度为零时重置行程开始时间
            if(drivingContinued.sd == 0.0){
              drivingContinued.setTs(newLocationTime)
              drivingContinued.setLt(lastTotalTime)
              //更新人脸识别的行程信息
              faceDrivingContinued = Some(DrivingContinuedIndex(vehicleNo, vehicleColor, drivingContinued.ln, drivingContinued.dn, DateTime.parse(newLocationTime, forPattern).getMillis.toString, null, "1"))
            }else {
              drivingContinued.setLt(cumulativeTime)
              //更新人脸识别的行程信息
              faceDrivingContinued = Some(DrivingContinuedIndex(vehicleNo, vehicleColor, drivingContinued.ln, drivingContinued.dn, DateTime.parse(drivingContinued.ts, forPattern).getMillis.toString, null, "1"))
            }

          }else{
            drivingContinued.setLt(cumulativeTime)
          }

          //更新周期开始时间
          if(lastCardTotalTime == 0){
            //速度为零时重置行程开始时间
            if(drivingContinued.sd == 0.0){
              drivingContinued.setCts(newLocationTime)
              drivingContinued.setLct(cardCumulativeTime)
              //更新IC卡的行程信息
              cardDrivingContinued = Some(DrivingContinuedIndex(vehicleNo, vehicleColor, drivingContinued.cln, drivingContinued.cdn, DateTime.parse(newLocationTime, forPattern).getMillis.toString, null, "2"))
            }else{
              drivingContinued.setLct(cardCumulativeTime)
              //更新IC卡的行程信息
              cardDrivingContinued = Some(DrivingContinuedIndex(vehicleNo, vehicleColor, drivingContinued.cln, drivingContinued.cdn, DateTime.parse(drivingContinued.cts, forPattern).getMillis.toString, null, "2"))
            }

          }else{
            drivingContinued.setLct(cardCumulativeTime)
          }

          drivingContinued.setSd(speed.toDouble)
          drivingContinued.setLlt(newLocationTime)
          //数据存入redis
          jedis.hset("drivingContinued", primaryKey, JSON.toJSONString(drivingContinued, SerializerFeature.QuoteFieldNames))

          //判断该点是否是挪车点
          val flag = isMovePoint(restContinuedTime, speed, locationDate, forPattern)
          //不是挪车点的情况才更新周期
          if(!flag){
            //更新人脸识别的行程信息
            faceDrivingContinued.foreach(x => CommonUtils.updateDrivingContinued(x))
            //更新IC卡的行程信息
            cardDrivingContinued.foreach(x => CommonUtils.updateDrivingContinued(x))
          }
          //更新挪车点信息
          updateMovePoint(restContinuedTime, speed, primaryKey, newLocationTime, jedis)
        } else {
          //速度为0的情况
          if (StringUtils.isNotEmpty(restContinuedTime)) {
            val restContinuedTimeArr: Array[String] = restContinuedTime.split("\\|")
            val restInterval: Int = restContinuedTimeArr(0).toInt
            val lastRestTime: String = restContinuedTimeArr(1)
            val num: Int = restContinuedTimeArr(2).toInt
            val lastRestDate = DateTime.parse(lastRestTime, forPattern)
            val speedSeconds = Seconds.secondsBetween(lastRestDate, locationDate).getSeconds
            var restIntervalSecond = restInterval
            var curSpeedTime = lastRestTime
            if (speedSeconds > 0) {
              restIntervalSecond = restInterval + speedSeconds
              curSpeedTime = dateTime
            }
            val movePoint: String = jedis.hget("movePointContinued", primaryKey)
            if (StringUtils.isNotEmpty(movePoint)) {
              val movePoints = movePoint.split(",")
              val firstPoint = DateTime.parse(movePoints(0), forPattern)
              val seconds1: Int = Seconds.secondsBetween(firstPoint, locationDate).getSeconds
              //休息20分钟，中间有挪车的情况周期结束，开启新的周期
              if (seconds1 >= 1200) {
                //新的人脸识别
                var currDriverName = ""
                var currLicenseNumber = ""
                if (StringUtils.isNotEmpty(businessTime)) {
                  try {
                    val businessMillis = DateTime.parse(businessTime, forPattern).getMillis
                    if(businessMillis > lastLocationDate.getMillis){
                      currDriverName = driverName
                      currLicenseNumber = licenseNumber
                    }
                  } catch {
                    case e: Exception => {
                      error(s"业务日期格式不对:${businessTime}")
                    }
                  }
                }

                //新的打卡数据
                var currCardDriverName = oldCardDriverName
                var currCardLicenseNumber = oldCardLicense
                if (StringUtils.isNotEmpty(signInTime)) {
                  currCardDriverName = signDriverName
                  currCardLicenseNumber = signLicense
                }

                val period = DrivingContinued(0, currLicenseNumber, currDriverName, 0, currCardLicenseNumber,
                  currCardDriverName, newLocationTime, newLocationTime, newLocationTime, speed.toDouble)

                jedis.hset("drivingContinued", primaryKey, JSON.toJSONString(period, SerializerFeature.QuoteFieldNames))
                //周期重新累计时，删除挪车点
                jedis.hdel("movePointContinued", primaryKey)
                val endTime = lastLocationDate.getMillis.toString
                if(lastTotalTime > 0) {
                  //更新人脸识别的行程信息
                  val drivingContinuedIndex = DrivingContinuedIndex(vehicleNo, vehicleColor, oldLicense, oldDriverName, tripStartMillis.toString, endTime, "1")
                  CommonUtils.updateDrivingContinued(drivingContinuedIndex)
                }
                if(lastCardTotalTime > 0){
                  //更新ic卡的行程信息
                  val signDrivingContinuedIndex = DrivingContinuedIndex(vehicleNo, vehicleColor, oldCardLicense, oldCardDriverName, cardTripStartMillis.toString, endTime, "2")
                  CommonUtils.updateDrivingContinued(signDrivingContinuedIndex)
                }
              } else {
                //继续累计时长
                jedis.hset("restContinuedTime", primaryKey, restIntervalSecond + "|" + curSpeedTime + "|" + num)
              }
            } else {
              //休息20分钟中间有速度小于二十，并且不超过五次的情况当成挪车，重置周期
              if (restIntervalSecond >= 1200 && num <= 5) {
                //新的人脸识别
                var currDriverName = ""
                var currLicenseNumber = ""
                if (StringUtils.isNotEmpty(businessTime)) {
                  try {
                    val businessMillis = DateTime.parse(businessTime, forPattern).getMillis
                    if(businessMillis > lastLocationDate.getMillis){
                      currDriverName = driverName
                      currLicenseNumber = licenseNumber
                    }
                  } catch {
                    case e: Exception => {
                      error(s"业务日期格式不对:${businessTime}")
                    }
                  }
                }

                //新的打卡数据
                var currCardDriverName = oldCardDriverName
                var currCardLicenseNumber = oldCardLicense
                if (StringUtils.isNotEmpty(signInTime)) {
                  currCardDriverName = signDriverName
                  currCardLicenseNumber = signLicense
                }

                val period = DrivingContinued(0, currLicenseNumber, currDriverName, 0, currCardLicenseNumber,
                  currCardDriverName, newLocationTime, newLocationTime, newLocationTime, speed.toDouble)

                jedis.hset("drivingContinued", primaryKey, JSON.toJSONString(period, SerializerFeature.QuoteFieldNames))
                //周期重新累计时，删除挪车点
                jedis.hdel("movePointContinued", primaryKey)
                val endTime = lastLocationDate.getMillis.toString
                if(lastTotalTime > 0) {
                  //更新人脸识别的行程信息
                  val drivingContinuedIndex = DrivingContinuedIndex(vehicleNo, vehicleColor, oldLicense, oldDriverName, tripStartMillis.toString, endTime, "1")
                  CommonUtils.updateDrivingContinued(drivingContinuedIndex)
                }
                if(lastCardTotalTime > 0){
                  //更新ic卡的行程信息
                  val signDrivingContinuedIndex = DrivingContinuedIndex(vehicleNo, vehicleColor, oldCardLicense, oldCardDriverName, cardTripStartMillis.toString, endTime, "2")
                  CommonUtils.updateDrivingContinued(signDrivingContinuedIndex)
                }
              } else {
                //新增速度为0判断
                jedis.hset("restContinuedTime", primaryKey, restIntervalSecond + "|" + curSpeedTime + "|" + num)
              }
            }
          } else {
            jedis.hset("restContinuedTime", primaryKey, "0|" + newLocationTime + "|0")
          }
        }
      } else {
        val period = DrivingContinued(0, licenseNumber, driverName,  0, signLicense,
          signDriverName, dateTime, dateTime, dateTime, speed.toDouble)
        jedis.hset("drivingContinued", primaryKey, JSON.toJSONString(period, SerializerFeature.QuoteFieldNames))
      }
    }
  }

  /**
    * 根据车牌号和车牌颜色及报警时间查询当前行驶周期开始时间
    * @param primaryKey
    * @param warnTime
    * @param jedis
    * @return
    */
  def getDrivingPeriodStart(primaryKey: String, warnTime: Long, jedis: Jedis): Long = {
    val forPattern = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")
    val format = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss")
    val mess = primaryKey.split("#")
    val vehicleNo: String = mess(0)
    val vehicleColor: String = mess(1)
    var tripStartMillis = 0L
    val drivingPeriodStr = jedis.hget("drivingPeriod", primaryKey)
    if (StringUtils.isNotEmpty(drivingPeriodStr)) {
      val drivingPeriod = JSON.parseObject(drivingPeriodStr, classOf[DrivingPeriod])
      //行程开始时间
      val tripStartTime: String = drivingPeriod.ts
      tripStartMillis = DateTime.parse(tripStartTime, forPattern).getMillis
      //行程已经结束的情况
      if (warnTime < tripStartMillis) {
        val warnTimeStr = format.format(warnTime)
        val tripStart = getDrivingPeriod(vehicleNo, vehicleColor, warnTimeStr)
        if (StringUtils.isNotEmpty(tripStart)) {
          tripStartMillis = DateTime.parse(tripStart, forPattern).getMillis
        }
      }
    } else {
      val warnTimeStr = format.format(warnTime)
      val tripStart = getDrivingPeriod(vehicleNo, vehicleColor, warnTimeStr)
      if (StringUtils.isNotEmpty(tripStart)) {
        tripStartMillis = DateTime.parse(tripStart, forPattern).getMillis
      }
    }

    tripStartMillis
  }

  /**
    * 根据车牌号和车牌颜色及时间查询行驶周期
    *
    * @param vehicleNo
    * @param vehicleColor
    * @param warnTime
    */
  def getDrivingPeriod(vehicleNo: String, vehicleColor: String, warnTime: String): String = {
    val searchBuilder = new SearchSourceBuilder()
    val queryBuilder = QueryBuilders.boolQuery()
    queryBuilder.must(QueryBuilders.rangeQuery("tripStartTime").lte(warnTime))
    queryBuilder.must(QueryBuilders.rangeQuery("tripEndTime").gt(warnTime))
    queryBuilder.must(QueryBuilders.termQuery("vehicleNo", vehicleNo))
    queryBuilder.must(QueryBuilders.termQuery("vehicleColor", vehicleColor))
    searchBuilder.query(queryBuilder)
    val query = searchBuilder.toString
    val jestClient = EsUtils.getClient()
    val search: Search = new Search.Builder(query).addIndex("driving_period_index").addType("driving_period_type").build()
    val resultSet: SearchResult = jestClient.execute(search)
    jestClient.close()
    val drivingPeriods = resultSet.getSourceAsObjectList(classOf[DrivingPeriodIndex], false)
    if (CollectionUtils.isNotEmpty(drivingPeriods)) {
      drivingPeriods.get(0).tripStartTime
    } else {
      ""
    }
  }

  /**
    * 更新挪车点信息
    * @param restContinuedTime
    * @param speed
    * @param primaryKey
    * @param newLocationTime
    * @param jedis
    */
  def updateMovePoint(restContinuedTime: String, speed: String, primaryKey: String, newLocationTime:String, jedis: Jedis): Unit ={
    if (StringUtils.isNotEmpty(restContinuedTime)) {
      var num = 0
      //如果速度小于20，则记录一次
      if (speed.toDouble <= 20.0) {
        val zeroTimes: Array[String] = restContinuedTime.split("\\|")
        val movePoint = jedis.hget("movePointContinued", primaryKey)
        if (StringUtils.isNotEmpty(movePoint)) {
          val movePoints: Array[String] = movePoint.split(",")
          if (movePoints.size < 5) {
            jedis.hset("movePointContinued", primaryKey, movePoints.mkString(",") + "," + newLocationTime)
          } else {
            val endSeat = movePoints.drop(1)
            jedis.hset("movePointContinued", primaryKey, endSeat.mkString(",") + "," + newLocationTime)
          }
        } else {
          jedis.hset("movePointContinued", primaryKey, newLocationTime)
        }
        num = zeroTimes(2).toInt
        jedis.hset("restContinuedTime", primaryKey, zeroTimes(0) + "|" + zeroTimes(1) + "|" + (num + 1))
      } else {
        //速度大于20的情况
        jedis.hdel("movePointContinued", primaryKey)
        //map重新置为空
        jedis.hset("restContinuedTime", primaryKey, 0 + "|" + newLocationTime + "|" + 0)
      }
    }
  }

  /**
    * 判断是否是挪车点
    * @param restContinuedTime
    * @param speed
    * @param locationDate
    * @param forPattern
    * @return
    */
  def isMovePoint(restContinuedTime: String, speed: String, locationDate: DateTime, forPattern: DateTimeFormatter): Boolean ={
    var flag = false
    if(StringUtils.isNotEmpty(restContinuedTime)){
      val restContinuedTimeArr: Array[String] = restContinuedTime.split("\\|")
      val restInterval: Int = restContinuedTimeArr(0).toInt
      val lastRestTime: String = restContinuedTimeArr(1)
      val num: Int = restContinuedTimeArr(2).toInt
      val lastRestDate = DateTime.parse(lastRestTime, forPattern)
      val speedSeconds = Seconds.secondsBetween(lastRestDate, locationDate).getSeconds
      var restIntervalSecond = restInterval
      if (speedSeconds > 0) {
        restIntervalSecond = restInterval + speedSeconds
      }
      if (restIntervalSecond >= 1200 && num <= 4 && speed.toDouble <= 20.0D) {
        flag = true
      }
    }
    flag
  }
}
